//
// Created on 2023/5/29.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".

#include "video_encoder_napi.h"
#include <multimedia/player_framework/native_avcodec_videoencoder.h>
#include "avcodec_callback_napi.h"
#include "avcodec_log.h"
#include <js_native_api.h>
#include <js_native_api_types.h>
#include <new>
#include <stdlib.h>
#include <string>
#include "avcodec_napi_utils.h"
#include "avcodec_video_encoder_demo.h"
#include "common/native_common.h"
#include "video_encoder.h"
#include "avcodec_napi_utils.h"
namespace OHOS {
namespace Media {

thread_local napi_ref VideoEncoderNapi::constructor_ = nullptr;
const std::string CLASS_NAME = "VideoEncoder";

VideoEncoderNapi::VideoEncoderNapi() {
    AVCODEC_LOGD("VideoEncoderNapi create");
}
VideoEncoderNapi::~VideoEncoderNapi() {
    AVCODEC_LOGD("~VideoEncoderNapi");
}

napi_value VideoEncoderNapi::Init(napi_env env, napi_value exports) {
    AVCODEC_LOGD("%s ", __FUNCTION__);
    napi_property_descriptor properties[] = {
        DECLARE_NAPI_FUNCTION("configure", Configure),
        DECLARE_NAPI_FUNCTION("prepare", Prepare),
        DECLARE_NAPI_FUNCTION("start", Start),
        DECLARE_NAPI_FUNCTION("stop", Stop),
        DECLARE_NAPI_FUNCTION("flush", Flush),
        DECLARE_NAPI_FUNCTION("reset", Reset),
        DECLARE_NAPI_FUNCTION("getOutputDescription", GetOutputDescription),
        DECLARE_NAPI_FUNCTION("sendFrameData", SendFrameData),
        DECLARE_NAPI_FUNCTION("release", Release),
        DECLARE_NAPI_FUNCTION("on", On)};

    napi_property_descriptor staticProperty[] = {
        DECLARE_NAPI_STATIC_FUNCTION("createVideoEncoder", CreateVideoEncoder),
    };

    napi_value constructor = nullptr;
    napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
                                           sizeof(properties) / sizeof(properties[0]), properties, &constructor);
    CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define VideoEncoder class");

    status = napi_create_reference(env, constructor, 1, &constructor_);
    CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to create reference of constructor");

    status = napi_set_named_property(env, exports, CLASS_NAME.c_str(), constructor);
    CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to set constructor");

    status = napi_define_properties(env, exports, sizeof(staticProperty) / sizeof(staticProperty[0]), staticProperty);
    CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define static function");

    AVCODEC_LOGD("Init success");

    return exports;
}

napi_value VideoEncoderNapi::Constructor(napi_env env, napi_callback_info info) {
    AVCODEC_LOGD("%s ", __FUNCTION__);
    napi_value result = nullptr;
    napi_get_undefined(env, &result);
    napi_value jsThis = nullptr;
    napi_status status = napi_get_cb_info(env, info, nullptr, nullptr, &jsThis, nullptr);
    if (status != napi_ok) {
        AVCODEC_LOGE("Failed to retrieve details about the callback");
        return result;
    }
    if (jsThis != nullptr) {
        VideoEncoderNapi *videoEncoderNapi = new (std::nothrow) VideoEncoderNapi();
        if (videoEncoderNapi != nullptr) {
            videoEncoderNapi->env_ = env;
            status = napi_wrap(env, jsThis, reinterpret_cast<void *>(videoEncoderNapi),
                               VideoEncoderNapi::Destructor, nullptr, nullptr);
            if (status != napi_ok) {
                delete videoEncoderNapi;
                AVCODEC_LOGE("Failed to warp native instance!");
                return result;
            }
        }
    }
    AVCODEC_LOGD("Constructor success");
    return jsThis;
}
void VideoEncoderNapi::Destructor(napi_env env, void *nativeObject, void *finalize) {
    (void)env;
    (void)finalize;
    if (nativeObject != nullptr) {
        VideoEncoderNapi *napi = reinterpret_cast<VideoEncoderNapi *>(nativeObject);
        delete napi;
    }
    AVCODEC_LOGD("Destructor success");
}

napi_value VideoEncoderNapi::CreateVideoEncoder(napi_env env, napi_callback_info info) {
    AVCODEC_LOGD("%s ", __FUNCTION__);
    napi_value result = nullptr;
    napi_get_undefined(env, &result);
    //创建napi对象
    napi_value ctor;
    napi_status status;
    status = napi_get_reference_value(env, constructor_, &ctor);
    if (status != napi_ok) {
        AVCODEC_LOGE("napi_get_reference_value fail");
        return result;
    }
    status = napi_new_instance(env, ctor, 0, nullptr, &result);
    if (status == napi_ok) {
        AVCODEC_LOGD("New instance success");
    } else {
        AVCODEC_LOGD("New instance could not be obtained");
    }
    return result;
}

napi_value VideoEncoderNapi::Configure(napi_env env, napi_callback_info info) {
    AVCODEC_LOGD("%s ", __FUNCTION__);
    napi_value result = nullptr;
    napi_get_undefined(env, &result);
    //获取arkts传过来参数信息
    napi_value thisVar = nullptr;
    napi_value args[ARGS1] = {nullptr};
    size_t argCount = ARGS1;
    napi_status status;
    status = napi_get_cb_info(env, info, &argCount, args, &thisVar, nullptr);
    CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
    //获取AvFormat
    AvFormat format = getAvFormat(env, args[PARAM0]);
    //获取napi实例
    VideoEncoderNapi *videoEncoderNapi = nullptr;
    getVideoEncoderNapi(env, thisVar, &videoEncoderNapi);
    if (videoEncoderNapi == nullptr)
        return result;
    int32_t ret;
    videoEncoderNapi->videoEncoder = VideoEncoderFactory::CreateByMime(format.codec_mime);
    ret = videoEncoderNapi->videoEncoder->configure(&format);
    videoEncoderNapi->codecCallback = std::make_shared<AvCodecCallbackNapi>();
    videoEncoderNapi->videoEncoder->SetCallback(videoEncoderNapi->codecCallback);
    AvCodecNapiUtils::createNapiInt32Value(env, ret, result);
    return result;
}
napi_value VideoEncoderNapi::Prepare(napi_env env, napi_callback_info info) {
    AVCODEC_LOGD("%s ", __FUNCTION__);
    napi_value result = nullptr;
    napi_value thisVar = nullptr;
    napi_get_undefined(env, &result);
    napi_status status;
    AVCODEC_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
    CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
    VideoEncoderNapi *videoEncoderNapi = nullptr;
    getVideoEncoderNapi(env, thisVar, &videoEncoderNapi);
    if (videoEncoderNapi == nullptr)
        return result;
    int32_t ret;
    ret = videoEncoderNapi->videoEncoder->prepare();
    AvCodecNapiUtils::createNapiInt32Value(env, ret, result);
    return result;
}

napi_value VideoEncoderNapi::Start(napi_env env, napi_callback_info info) {
    AVCODEC_LOGD("%s ", __FUNCTION__);
    napi_value result = nullptr;
    napi_value thisVar = nullptr;
    napi_get_undefined(env, &result);
    napi_status status;
    AVCODEC_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
    CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
    VideoEncoderNapi *videoEncoderNapi = nullptr;
    getVideoEncoderNapi(env, thisVar, &videoEncoderNapi);
    if (videoEncoderNapi == nullptr)
        return result;
    int32_t ret;
    ret = videoEncoderNapi->videoEncoder->start();
    AvCodecNapiUtils::createNapiInt32Value(env, ret, result);
    return result;
}
napi_value VideoEncoderNapi::Stop(napi_env env, napi_callback_info info) {
    AVCODEC_LOGD("%s ", __FUNCTION__);
    napi_value result = nullptr;
    napi_value thisVar = nullptr;
    napi_get_undefined(env, &result);
    napi_status status;
    AVCODEC_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
    CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
    VideoEncoderNapi *videoEncoderNapi = nullptr;
    getVideoEncoderNapi(env, thisVar, &videoEncoderNapi);
    if (videoEncoderNapi == nullptr)
        return result;
    int32_t ret;
    ret = videoEncoderNapi->videoEncoder->stop();
    AvCodecNapiUtils::createNapiInt32Value(env, ret, result);
    return result;
}
napi_value VideoEncoderNapi::Flush(napi_env env, napi_callback_info info) {
    AVCODEC_LOGD("%s ", __FUNCTION__);
    napi_value result = nullptr;
    napi_value thisVar = nullptr;
    napi_get_undefined(env, &result);
    napi_status status;
    AVCODEC_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
    CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
    VideoEncoderNapi *videoEncoderNapi = nullptr;
    getVideoEncoderNapi(env, thisVar, &videoEncoderNapi);
    if (videoEncoderNapi == nullptr)
        return result;
    int32_t ret;
    ret = videoEncoderNapi->videoEncoder->flush();
    AvCodecNapiUtils::createNapiInt32Value(env, ret, result);
    return result;
}
napi_value VideoEncoderNapi::Reset(napi_env env, napi_callback_info info) {
    AVCODEC_LOGD("%s ", __FUNCTION__);
    napi_value result = nullptr;
    napi_value thisVar = nullptr;
    napi_get_undefined(env, &result);
    napi_status status;
    AVCODEC_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
    CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
    VideoEncoderNapi *videoEncoderNapi = nullptr;
    getVideoEncoderNapi(env, thisVar, &videoEncoderNapi);
    if (videoEncoderNapi == nullptr)
        return result;
    int32_t ret;
    ret = videoEncoderNapi->videoEncoder->rest();
    AvCodecNapiUtils::createNapiInt32Value(env, ret, result);
    return result;
}
napi_value VideoEncoderNapi::GetOutputDescription(napi_env env, napi_callback_info info) {
    AVCODEC_LOGD("%s ", __FUNCTION__);
    napi_value result = nullptr;
    napi_value thisVar = nullptr;
    napi_get_undefined(env, &result);
    napi_status status;
    AVCODEC_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
    CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
    VideoEncoderNapi *videoEncoderNapi = nullptr;
    getVideoEncoderNapi(env, thisVar, &videoEncoderNapi);
    if (videoEncoderNapi == nullptr)
        return result;
    std::string des = "";
    des = videoEncoderNapi->videoEncoder->getOutputDescription();
    AvCodecNapiUtils::createNapiStringValue(env, des, result);
    return result;
}
napi_value VideoEncoderNapi::Release(napi_env env, napi_callback_info info) {
    AVCODEC_LOGD("%s ", __FUNCTION__);
    napi_value result = nullptr;
    napi_value thisVar = nullptr;
    napi_get_undefined(env, &result);
    napi_status status;
    AVCODEC_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
    CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
    VideoEncoderNapi *videoEncoderNapi = nullptr;
    getVideoEncoderNapi(env, thisVar, &videoEncoderNapi);
    if (videoEncoderNapi == nullptr)
        return result;
    int32_t ret;
    ret = videoEncoderNapi->videoEncoder->release();
    AvCodecNapiUtils::createNapiInt32Value(env, ret, result);
    return result;
}

napi_value VideoEncoderNapi::SendFrameData(napi_env env, napi_callback_info info) {
    napi_value result = nullptr;
    napi_get_undefined(env, &result);
    napi_value thisVar = nullptr;
    napi_status status;
    size_t argc = ARGS3;
    napi_value argv[ARGS3] = {nullptr};
    AVCODEC_LOGD("VideoEncoderNapi::SendFrameData napi_env = %p", env);
    napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
    //获取napi实例
    VideoEncoderNapi *videoEncoderNapi = nullptr;
    getVideoEncoderNapi(env, thisVar, &videoEncoderNapi);
    if (videoEncoderNapi == nullptr)
        return result;
    if (argc == ARGS3) {
        int32_t dataLen = 0;
        AvCodecNapiUtils::getNapiInt32Value(env, argv[PARAM1], dataLen);
        if (dataLen <= 0) {
            AVCODEC_LOGE("NAPI: %{public}s dataLen(%{public}d) <= 0.", __FUNCTION__, dataLen);
            return result;
        }

        int realSize = 0;
        uint8_t *data = nullptr;
        if (!AvCodecNapiUtils::getNapiCharArrFromUint8Arr(env, argv[PARAM0], &data, 0, realSize, false)) {
            AVCODEC_LOGE("NAPI:%{public}s getNapiCharArrFromUint8Arr(data) err", __FUNCTION__);
        }

        int64_t timestamp = 0;
        AvCodecNapiUtils::getNapiInt64Value(env, argv[PARAM2], timestamp);
        videoEncoderNapi->videoEncoder->sendFrameData(data, dataLen, timestamp);
    } else {
        AVCODEC_LOGE("NAPI: %{public}s argc(%{public}d) not enough, need %d.", __FUNCTION__, argc, ARGS3);
    }
    return result;
}
napi_value VideoEncoderNapi::On(napi_env env, napi_callback_info info) {
    napi_value result = nullptr;
    napi_get_undefined(env, &result);
    napi_value thisVar = nullptr;
    napi_status status;
    size_t argc = ARGS2;
    napi_value argv[ARGS2] = {nullptr};
    napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
    VideoEncoderNapi *videoEncoderNapi = nullptr;
    getVideoEncoderNapi(env, thisVar, &videoEncoderNapi);
    if (videoEncoderNapi == nullptr)
        return result;
    napi_valuetype valueType = napi_undefined;
    if (napi_typeof(env, argv[PARAM0], &valueType) != napi_ok || valueType != napi_string || napi_typeof(env, argv[PARAM1], &valueType) != napi_ok || valueType != napi_function) {
        return result;
    }
    std::string eventType;
    eventType = AvCodecNapiUtils::getNapiStringValue(env, argv[PARAM0]);
    napi_ref callbackRef;
    const int32_t refCount = 1;
    napi_create_reference(env, argv[PARAM1], refCount, &callbackRef);
    if (!eventType.empty() && (eventType.compare("OnOutputBufferAvailable") == 0)) {
        videoEncoderNapi->codecCallback->setOutputBufferAvailableCb(env, callbackRef);
    } else if (!eventType.empty() && (eventType.compare("onError") == 0)) {
        videoEncoderNapi->codecCallback->setOnErrorCb(env, callbackRef);
    } else if (!eventType.empty() && (eventType.compare("OnOutputFormatChanged") == 0)) {
        videoEncoderNapi->codecCallback->setOnOutputFormatChangeCb(env, callbackRef);
    } else if (!eventType.empty() && (eventType.compare("codecDataArrival") == 0)) {
        videoEncoderNapi->codecCallback->setInputBufferAvailableCb(env, callbackRef);
    } else {
        AVCODEC_LOGE("Incorrect callback event type provided for video encoder !");
        if (callbackRef != nullptr) {
            napi_delete_reference(env, callbackRef);
        }
    }
    return result;
}

static bool JsOnQueryArgs(VideoEncoderCommonArgs &args, VideoEncoderInnerContext &ic)
{
    if (ic.argc == ARGS2) {
        auto argType0 = AvCodecNapiUtils::getType(args.env, ic.argv[PARAM0]);
        auto argType1 = AvCodecNapiUtils::getType(args.env, ic.argv[PARAM1]);
        if (argType0 == napi_string && argType1 == napi_function) {
            napi_create_reference(args.env, ic.argv[PARAM1], ic.refCount, &(ic.context->callbackRef));
        } 
    } else {
        return false;
    }

    napi_get_undefined(args.env, &ic.result);
    return true;
}

static bool CheckArgs(const VideoEncoderCommonArgs &args)
{
    if (args.async != CallType::GETTER) {
        if (args.queryArgs == nullptr) {
            AVCODEC_LOGE("No query args function");
            return false;
        }
    }

    if (args.async != CallType::ASYNC || args.asyncLater) {
        if (args.nonAsyncBack == nullptr) {
            AVCODEC_LOGE("No non async back function");
            return false;
        }
    }
    return true;
}


napi_value VideoEncoderNapi::JSCommonProcess(VideoEncoderCommonArgs &args)
{
    struct VideoEncoderInnerContext ic;
    ic.argc = args.argc;
    ic.argv.resize(ic.argc);
    napi_get_undefined(args.env, &ic.result);

    IMG_NAPI_CHECK_RET(CheckArgs(args), ic.result);

    IMG_JS_ARGS(args.env, args.info, ic.status, ic.argc, &(ic.argv[0]), ic.thisVar);

    IMG_NAPI_CHECK_RET_D(IMG_IS_OK(ic.status), ic.result, AVCODEC_LOGE("fail to napi_get_cb_info"));

    if (args.async != CallType::STATIC) {
        ic.context = std::make_unique<VideoEncoderAsyncContext>();
        if (ic.context == nullptr) {
            return ic.result;
        }
        ic.status = napi_unwrap(args.env, ic.thisVar, reinterpret_cast<void**>(&(ic.context->constructor_)));

        IMG_NAPI_CHECK_RET_D(IMG_IS_READY(ic.status, ic.context->constructor_),
            ic.result, AVCODEC_LOGE("fail to unwrap context"));

        if (ic.context->constructor_ == nullptr) {
            return ic.result;
        }
        ic.context->encoder_ = ic.context->constructor_->videoEncoder;

        IMG_NAPI_CHECK_RET_D(IMG_IS_READY(ic.status, ic.context->encoder_),
            ic.result, AVCODEC_LOGE("empty native receiver"));
    }
    if (args.async != CallType::GETTER) {
        if (!args.queryArgs(args, ic)) {
            return ic.result;
        }
    }

    if (args.async == CallType::ASYNC) {
        if (args.asyncLater) {
            args.nonAsyncBack(args, ic);
        } else {
            napi_value _resource = nullptr;
            napi_create_string_utf8((args.env), (args.name.c_str()), NAPI_AUTO_LENGTH, &_resource);
            (ic.status) = napi_create_async_work(args.env, nullptr, _resource,
                                                 ([](napi_env env, void *data) {}),
                                                 (reinterpret_cast<napi_async_complete_callback>(args.callBack)),
                                                 static_cast<void *>((ic.context).get()), &(ic.context->work));
            napi_queue_async_work((args.env), (ic.context->work));
            ic.context.release();
        }
    } else {
        args.nonAsyncBack(args, ic);
    }

    return ic.result;
}

napi_value VideoEncoderNapi::JsOn(napi_env env, napi_callback_info info) {
    VideoEncoderCommonArgs args = {
        .env = env, .info = info,
        .async = CallType::ASYNC,
        .name = "JsOn",
    };
    args.argc = ARGS2;
    args.asyncLater = true;
    args.queryArgs = JsOnQueryArgs;
        args.nonAsyncBack = [](VideoEncoderCommonArgs &args, VideoEncoderInnerContext &ic) -> bool {
            napi_get_undefined(args.env, &(ic.result));
    
            auto native = ic.context->constructor_->videoEncoder;
            if (native == nullptr) {
                AVCODEC_LOGE("Native instance is nullptr");
                ic.context->status = -1;
                return false;
            }
            std::shared_ptr<OHOS::Media::VideoEncoderAvaliableListener> listener = std::make_shared<OHOS::Media::VideoEncoderAvaliableListener>();
            listener->context = std::move(ic.context);
            listener->context->env = args.env;
            listener->name = args.name;
    
            AVCODEC_LOGE("listener is %{public}p", listener.get());
    
            native->SetCallback((std::shared_ptr<AVCodecCallback> &)listener);
        
            return true;
        };
     return JSCommonProcess(args);
}
void VideoEncoderNapi::DoCallBack(std::shared_ptr<VideoEncoderAsyncContext> context,
                                   std::string name, CompleteCallback callBack)
{
    IMAGE_FUNCTION_IN();
    if (context == nullptr) {
        AVCODEC_LOGE("gContext is empty");
        return;
    }
    if (context->env == nullptr) {
        AVCODEC_LOGE("env is empty");
        return;
    }

    uv_loop_s *loop = nullptr;
    napi_get_uv_event_loop(context->env, &loop);
    if (loop == nullptr) {
        AVCODEC_LOGE("napi_get_uv_event_loop failed");
        return;
    }

    std::unique_ptr<uv_work_t> work = std::make_unique<uv_work_t>();
    if (work == nullptr) {
        AVCODEC_LOGE("DoCallBack: No memory");
        return;
    }
    work->data = reinterpret_cast<void *>(context.get());
    int ret = uv_queue_work(loop, work.get(), [] (uv_work_t *work) {}, [] (uv_work_t *work, int status) {
        IMAGE_LINE_IN();
        Context context = reinterpret_cast<Context>(work->data);
        if (context == nullptr) {
            AVCODEC_LOGE("context is empty");
        } else {
            napi_value result[PARAM2] = {0};
            napi_value retVal;
            napi_value callback = nullptr;
            if (context->env != nullptr && context->callbackRef != nullptr) {
                napi_create_uint32(context->env, 0, &result[0]);
                napi_get_undefined(context->env, &result[1]);
                napi_get_reference_value(context->env, context->callbackRef, &callback);
                if (callback != nullptr) {
                    napi_call_function(context->env, nullptr, callback, PARAM2, result, &retVal);
                } else {
                    AVCODEC_LOGE("napi_get_reference_value callback is empty");
                }
            } else {
                AVCODEC_LOGE("env or callbackRef is empty");
            }
        }
        delete work;
        IMAGE_LINE_OUT();
    });
    if (ret != 0) {
        AVCODEC_LOGE("Failed to execute DoCallBack work queue");
    } else {
        work.release();
    }
    IMAGE_FUNCTION_OUT();
}




void VideoEncoderNapi::getVideoEncoderNapi(napi_env env, napi_value thisVar, VideoEncoderNapi **result) {
    napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(result));
    if (status != napi_ok || result == nullptr) {
        AVCODEC_LOGE("get videoEncoderNapi fail");
    }
}

AvFormat VideoEncoderNapi::getAvFormat(napi_env env, napi_value value) {
    AVCODEC_LOGD("VideoEncoderNapi::%{public}s called", __FUNCTION__);
    AvFormat avFormat;
    avFormat.codec_mime = AvCodecNapiUtils::getObjPropStringValue(env, value, "mime");
    AvCodecNapiUtils::getObjPropInt32Value(env, value, "encodeBitRate", avFormat.bitrate);
    AvCodecNapiUtils::getObjPropInt32Value(env, value, "width", avFormat.width);
    AvCodecNapiUtils::getObjPropInt32Value(env, value, "height", avFormat.height);
    AvCodecNapiUtils::getObjPropInt32Value(env, value, "pixelFormat", avFormat.pixel_format);
    AvCodecNapiUtils::getObjPropInt32Value(env, value, "frameRate", avFormat.frame_rate);
    AvCodecNapiUtils::getObjPropInt32Value(env, value, "iFrameIntervalMs", avFormat.i_frame_interval);
    AvCodecNapiUtils::getObjPropInt32Value(env, value, "codecQuality", avFormat.codec_quality);
    AvCodecNapiUtils::getObjPropInt32Value(env, value, "codecProfile", avFormat.codec_profile);
    AvCodecNapiUtils::getObjPropInt32Value(env, value, "videoEncodeBitRateMode", avFormat.video_encode_bitrate_mode);
    AVCODEC_LOGD("avFormat{mime:%{public}s,encodeBitRate:%{public}d,iFrameIntervalMs:%{public}d,", avFormat.codec_mime.c_str(), avFormat.bitrate, avFormat.i_frame_interval);
    AVCODEC_LOGD("width:%{public}d,height:%{public}d,pixelFormat:%{public}d,", avFormat.width, avFormat.height, avFormat.pixel_format);
    AVCODEC_LOGD("frameRate:%{public}d,codecQuality:%{public}d,codecProfile:%{public}d,videoEncodeBitRateMode:%{public}d}", avFormat.frame_rate, avFormat.codec_quality, avFormat.codec_profile, avFormat.video_encode_bitrate_mode);
    return avFormat;
}

} // namespace Media
} // namespace OHOS
